package com.zzy.demo.common.util.sm2hutool;

import java.nio.charset.Charset;

import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.signers.PlainDSAEncoding;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.junit.Test;

import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.BCUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.SM2;

public class SM2Hutool {
	
	public static String privateKey ="01d27906b045a27c4bf40e7bab93b8041d3e5ed8b3d9215b99eb923ffbb4cef1";
	public static String publicKey ="04513e4d89a5d87de71fc9e84cc563818f2bcb1c154a60f5ee496b4621f214c7cd6367166bb52aaddd306013748ff3fe6463264f4d8689456159979c8da6c7d660";
	
    /**
     * 创建sm2测试
     * <i scr="https://i.goto327.top/CryptTools/SM2.aspx?tdsourcetag=s_pctim_aiomsg">秘钥验证</i>
     */
    @Test
    public void createSm2KeyTest() {

        //创建sm2 对象
        SM2 sm2 = SmUtil.sm2(privateKey, publicKey);
        //这里会自动生成对应的随机秘钥对 , 注意！ 这里一定要强转，才能得到对应有效的秘钥信息
        byte[] privateKey = BCUtil.encodeECPrivateKey(sm2.getPrivateKey());
        //这里公钥不压缩  公钥的第一个字节用于表示是否压缩  可以不要
        byte[] publicKey = ((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false);
        
        //这里得到的 压缩后的公钥 
        // ((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(true);
        // byte[] publicKeyEc = BCUtil.encodeECPublicKey(sm2.getPublicKey());
        
        
        //打印当前的公私秘钥
        System.out.println("私钥: " + HexUtil.encodeHexStr(privateKey));
        System.out.println("公钥: " + HexUtil.encodeHexStr(publicKey));

        
    }
    
    
    @Test
    public void sm2Test() {

        //创建sm2 对象
        SM2 sm2 = SmUtil.sm2(privateKey, publicKey);
        
        //这里需要手动设置，sm2 对象的默认值与我们期望的不一致
        sm2.setMode(SM2Engine.Mode.C1C2C3);
        sm2.setEncoding(new PlainDSAEncoding());
        //sm2.setEncoding(new StandardDSAEncoding());
        

        //需要加密的明文
        String text = "我是一段测试aaaa";
        byte[] dateBytes = text.getBytes();
        System.out.println("数据: " + HexUtil.encodeHexStr(dateBytes));

        
        byte[] encodeData =  sm2.encrypt(dateBytes);
        String encodeHex =  HexUtil.encodeHexStr(encodeData);
        System.out.println("加密:" + encodeHex);
        
        
        byte[] encodeData2 = HexUtil.decodeHex(encodeHex);
        byte[] decodeData =  sm2.decrypt(encodeData2);
        String decodeStr =  new String (decodeData, Charset.forName("UTF-8"));
        System.out.println("解密:" + decodeStr);
        
        
//        //计算签名
//        byte[] sign = sm2.sign(dateBytes, null);
//        System.out.println("签名: " + HexUtil.encodeHexStr(sign));
//        // 校验  验签
//        boolean verify = sm2.verify(dateBytes, sign);
//        System.out.println(verify);
        
    }
    
    
    @Test
    public void sm2SignTest() {

        //创建sm2 对象
        SM2 sm2 = SmUtil.sm2(privateKey, publicKey);
        
        //这里需要手动设置，sm2 对象的默认值与我们期望的不一致
        sm2.setMode(SM2Engine.Mode.C1C2C3);
        sm2.setEncoding(new PlainDSAEncoding());
        //sm2.setEncoding(new StandardDSAEncoding());
        

        //需要加密的明文
        String text = "我是一段测试aaaa";
        byte[] dateBytes = text.getBytes();

        
        //计算签名
        byte[] sign = sm2.sign(dateBytes, null);
        System.out.println("签名: " + HexUtil.encodeHexStr(sign));
        // 校验  验签
        boolean verify = sm2.verify(dateBytes, sign);
        System.out.println(verify);
        
    }

    public static void main(String[] args) {
        SM2 mySm2 = SmUtil.sm2(privateKey, publicKey);
        mySm2.setMode(SM2Engine.Mode.C1C3C2);
        mySm2.setEncoding(new PlainDSAEncoding());
        
        String hexStr ="041041757771723ad521e7d2eef80fda674ef93a5134db8bb93a491bf34cc1b32a936a1ae562ad5f9dfebe191bd28bd6cf61388855c2d42024f19df2e8a5c086c5c08d70a09e6892d7a639c5f0376690009ddd40cbc3b8fefc8cc91eb768d9f20ff910b6496e2e6bdd7ed1f8eb31564fc3754457ac6209";
        
        byte[] encodeData = HexUtil.decodeHex(hexStr);
        byte[] decodeData =  mySm2.decrypt(encodeData);
        String decodeStr =  new String (decodeData, Charset.forName("UTF-8"));
        System.out.println("解密:" + decodeStr);
	}

}
